package com.jiexin.service;

import com.google.common.base.Preconditions;
import com.jiexin.common.RequestHolder;
import com.jiexin.dao.SysDeptMapper;
import com.jiexin.dao.SysUserMapper;
import com.jiexin.exception.ParamException;
import com.jiexin.model.SysDept;
import com.jiexin.param.DeptParam;
import com.jiexin.util.BeanValidator;
import com.jiexin.util.IpUtil;
import com.jiexin.util.LevelUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @Author: Jay_Liu
 * @Description:
 * @Date: Created in 19:52 2018/4/3 0003
 * @Modified By:
 */
@Service
public class SysDeptService {

    @Resource
    private SysDeptMapper sysDeptMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysLogService sysLogService;
    //保存
    public void save(DeptParam deptParam){
        //检查对象是否满足对应字段条件
        BeanValidator.check(deptParam);
        if(checkExist(deptParam.getParentId(), deptParam.getName(), deptParam.getId())) {
            throw new ParamException("同一层级存在相同名称的部门");
        }
        //建造者方式创建对象
        SysDept dept = SysDept.builder().name(deptParam.getName()).parentId(deptParam.getParentId())
                .seq(deptParam.getSeq()).remark(deptParam.getRemark()).build();
        //设置部门等级
        dept.setLevel(LevelUtil.calculateLevel(getLevel(dept.getParentId()), dept.getParentId()));
        //获取当前线程中的用户信息
        dept.setOperator(RequestHolder.getCurrentUser().getUsername());
        //根据请求获取IP
        dept.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
        dept.setOperateTime(new Date());
        //插入
        sysDeptMapper.insertSelective(dept);
        sysLogService.saveDeptLog(null, dept);
    }

    //更新部门
    public void update(DeptParam deptParam){
        //检查对象是否满足对应字段条件
        BeanValidator.check(deptParam);
        if(checkExist(deptParam.getParentId(), deptParam.getName(), deptParam.getId())) {
            throw new ParamException("同一层级存在相同名称的部门");
        }
        //附加程序：04.18
        if(deptParam.getParentId() == deptParam.getId()) {
            throw new ParamException("不允许移动到部门本身的下属部门");
        }
        //修改前部门对象
        SysDept before = sysDeptMapper.selectByPrimaryKey(deptParam.getId());
        Preconditions.checkNotNull(before, "待更新的部门不存在");
        if(checkExist(deptParam.getParentId(), deptParam.getName(), deptParam.getId())) {
            throw new ParamException("同一层级存在相同名称的部门");
        }
        //修改后部门对象
        SysDept after = SysDept.builder().id(deptParam.getId()).name(deptParam.getName()).parentId(deptParam.getParentId())
                .seq(deptParam.getSeq()).remark(deptParam.getRemark()).build();
        //设置部门等级
        after.setLevel(LevelUtil.calculateLevel(getLevel(deptParam.getParentId()),deptParam.getParentId()));
        after.setOperator(RequestHolder.getCurrentUser().getUsername());
        after.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
        after.setOperateTime(new Date());
        updateWithChild(before, after);
        sysLogService.saveDeptLog(before, after);
    }

    //更新部门
    @Transactional
    public void updateWithChild(SysDept before, SysDept after) {

        String newLevelPrefix = after.getLevel();
        String oldLevelPrefix = before.getLevel();
        if(!after.getLevel().equals(before.getLevel())) {
            //通过部门等级获取所有子部门
            //原程序:
            //List<SysDept> deptList = sysDeptMapper.getChildDeptListByLevel(before.getLevel());
            //新程序：获取当前部门所有子部门(当前等级+当前ID = 下级部门等级的前缀)
            List<SysDept> deptList = sysDeptMapper.getChildDeptListByLevel(LevelUtil.calculateLevel(before.getLevel(),before.getId()));
            if(CollectionUtils.isNotEmpty(deptList)) {
                for (SysDept dept : deptList) {
                    String level = dept.getLevel();
                    //若是以旧level前缀的，则更新level
                    if (level.indexOf(oldLevelPrefix) == 0) {
                        //拼接新的level
                        level = newLevelPrefix + level.substring(oldLevelPrefix.length());
                        dept.setLevel(level);
                    }
                }
                //批量更新子部门的level
                sysDeptMapper.batchUpdateLevel(deptList);
            }
        }
        sysDeptMapper.updateByPrimaryKey(after);
    }

    //同一级部门下是否存在相同部门
    private boolean checkExist(Integer parentId, String deptName, Integer deptId){
        return sysDeptMapper.countByNameAndParentId(parentId, deptName, deptId) > 0;
    }

    //根据部门id找到部门等级
    private String getLevel(Integer deptId) {
        SysDept dept = sysDeptMapper.selectByPrimaryKey(deptId);
        if (dept == null) {
            return null;
        }
        return dept.getLevel();
    }


    public void delete(int deptId) {
        SysDept dept = sysDeptMapper.selectByPrimaryKey(deptId);
        Preconditions.checkNotNull(dept,"删除的部门不存在");
        //查看当前部门下是否有子部门
        if(sysDeptMapper.countByParentId(deptId) > 0 ){
            throw new ParamException("当前部门下有子部门,无法删除");
        }
        //查看当前部门下是否有用户
        if(sysUserMapper.countByDeptId(deptId) > 0 ){
            throw new ParamException("当前部门下有用户,无法删除");
        }
        //删除
        sysDeptMapper.deleteByPrimaryKey(deptId);
    }
}
